﻿/*
 * Copyright 2010 Pieter De Rycke
 *
 * This file is part of Frozen Bubble XNA.
 *
 * Frozen Bubble XNA is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2, as published by the Free Software Foundation.
 *
 * Frozen Bubble XNA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with Frozen Bubble XNA. If not, see 
 * <http://www.gnu.org/licenses/>.
 *
 * Artwork:
 *    Alexis Younes <73lab at free.fr>
 *      (everything but the bubbles)
 *    Amaury Amblard-Ladurantie <amaury at linuxfr.org>
 *      (the bubbles)
 *
 * Soundtrack:
 *    Matthias Le Bidan <matthias.le_bidan at caramail.com>
 *      (the three musics and all the sound effects)
 *
 * Design & Programming:
 *    Guillaume Cottenceau <guillaume.cottenceau at free.fr>
 *      (design and manage the project, whole Perl sourcecode)
 *
 * XNA and Windows Phone 7 port:
 *    Pieter De Rycke
 *
 * Websites:
 *    http://www.frozen-bubble.org/
 *    http://pieterderycke.wordpress.com/
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Reflection;
using System.Diagnostics;

namespace FrozenBubble
{
    public class CanonSprite : IScreenComponent
    {
#if WINDOWS_PHONE
        private const float CanonScale = 4.0f / 3.0f;
#else
        private const float CanonScale = 1.0f;
#endif

        private GameScreen _screen;

        private Dictionary<int, Texture2D> _cannons;
        private Dictionary<int, Vector2> _offsets;

        private double _angle;
        private int _number;
        
        public CanonSprite(GameScreen screen)
        {
            _screen = screen;
        }

        public void LoadContent()
        {
#if DEBUG
            long start = DateTime.Now.Ticks;
#endif
            //load the cannon data
            _cannons = _screen.Cache.Cannons;
            //_cannons = new Dictionary<int, Texture2D>();
            //for (int i = -BubbleConstants.CANON_ROTATIONS_NB; i < BubbleConstants.CANON_ROTATIONS_NB; i++)
                //_cannons.Add(i, _screen.Game.Content.Load<Texture2D>("Graphics/Shoot/base_" + i));

            //load offset information
            _offsets = new Dictionary<int, Vector2>();
            string data = ReadFile("FrozenBubble.data");
            string[] lines = data.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in lines)
            {
                string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                Vector2 offset = new Vector2(Int32.Parse(parts[1]) * CanonScale, Int32.Parse(parts[2]) * CanonScale);
                int number = Int32.Parse(parts[0]);
                if (!_offsets.ContainsKey(number))
                    _offsets.Add(number, offset);
            }

#if DEBUG
            long loadTime = (DateTime.Now.Ticks - start) / 10000;
            Debug.WriteLine("Loadtime CanonSprite.cs: " + loadTime);
#endif
        }

        public void UnloadContent()
        { }

        private string ReadFile(string path)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            StringBuilder sb = new StringBuilder();
            StreamReader reader = new StreamReader(assembly.GetManifestResourceStream(path));
            string line = reader.ReadLine();
            while (line != null)
            {
                sb.Append(line);
                sb.Append("\n");
                line = reader.ReadLine();
            }
            reader.Close();
            return sb.ToString();
        }

        public void Update(GameTime gameTime)
        {
            InputState input = _screen.Input.State;

            if(input.IsActionActive(InputAction.Left))
                _angle += BubbleConstants.LAUNCHER_SPEED;
            else if(input.IsActionActive(InputAction.Right))
                _angle -= BubbleConstants.LAUNCHER_SPEED;

            if (input.IsActionActive(InputAction.Center))
            {
                if (_angle >= Math.PI / 2 - BubbleConstants.LAUNCHER_SPEED
                    && _angle <= Math.PI / 2 + BubbleConstants.LAUNCHER_SPEED)
                {
                    _angle = Math.PI / 2;
                }
                else
                {
                    _angle += (_angle < Math.PI / 2) ? BubbleConstants.LAUNCHER_SPEED : -BubbleConstants.LAUNCHER_SPEED;
                }
            }

            if (_angle < 0.1)
                _angle = 0.1;
            if (_angle > Math.PI - 0.1)
                _angle = Math.PI - 0.1;

            //update current texture
            _number = (int)(_angle * BubbleConstants.CANON_ROTATIONS_NB / (Math.PI / 2) + 0.5) - BubbleConstants.CANON_ROTATIONS_NB;
        }

        public double Angle
        {
            get
            {
                return _angle;
            }
        }

        public Texture2D Texture
        {
            get
            {
                return _cannons[_number];
            }
        }

        public float OffsetX
        {
            get
            {
                return _offsets[_number].X;
            }
        }

        public float OffsetY
        {
            get
            {
                return _offsets[_number].Y;
            }
        }

        public void Reset()
        {
            _angle = Math.PI / 2;
        }
    }
}
